package megrez.job.custom.component;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import lombok.RequiredArgsConstructor;
import megrez.job.common.StringHelper;
import megrez.job.custom.domain.Config;
import megrez.job.custom.domain.ConfigRepository;
import megrez.job.custom.domain.ConfigService;
import megrez.job.custom.domain.Log;
import megrez.job.custom.domain.LogRepository;
import megrez.job.custom.utils.TaskStateException;

/**
 * 任务服务
 * 
 * @author Lucky Yang
 * @since 2.6.9
 */
@Component
@RequiredArgsConstructor
public class TaskService {
    private final LogRepository logRepo;
    private final ConfigService configeSrc;
    private final ConfigRepository configRep;

    @Transactional(rollbackFor = Exception.class)
    public void run(Task task) {
        task.getMonitor().run();
        saveTaskToLog(new Task(task));
    }

    @Transactional(rollbackFor = Exception.class)
    public void start(Task task) {
        task.getMonitor().start();
        saveTaskToLog(new Task(task));
    }

    @Transactional(rollbackFor = Exception.class)
    public void complete(Task task) {
        task.getMonitor().complete();
        saveTaskToLog(new Task(task));
    }

    @Transactional(rollbackFor = Exception.class)
    public void stop(Task task) {
        task.getMonitor().stop();
        saveTaskToLog(new Task(task));
    }

    @Transactional(rollbackFor = Exception.class)
    public void error(Task task, String error) {
        task.getMonitor().error(error);
        saveTaskToLog(new Task(task));
    }

    /**
     * 将当前工作任务信息保存到日志
     * 
     * @param task
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveTaskToLog(Task task) {
        Config config = configeSrc.findById(task.getConfig().getId());
        Log log = new Log();
        log.setConfig(config);
        log.setConfigSnapshot(task.getConfig().toString());
        log.setCostTime(task.getMonitor().getCostTime());
        log.setState(task.getMonitor().getState());
        log.setMessage(StringHelper.limitLength(task.getMonitor().getMessage(), 3999));
        logRepo.save(log);
    }

    @Transactional(rollbackFor = Exception.class)
    public Config removeConfig(String configId) {
        Config config = configeSrc.findById(configId);

        if (ScheduledTaskContainer.isStarted(Task.of(config))) {
            throw new TaskStateException();
        }
        configRep.delete(config);
        ScheduledTaskContainer.remove(Task.of(config));
        return config;
    }

    @Transactional(rollbackFor = Exception.class)
    public Config createConfig(Config config) {
        Assert.isNull(config.getId(), "config cannt create");

        Config rslt = configRep.save(config);
        // 加入到容器
        ScheduledTaskContainer.put(Task.of(rslt), ScheduledFutureTaskHolder.emptyHolder());
        return rslt;
    }

    @Transactional(rollbackFor = Exception.class)
    public Config updateConfig(Config config) {
        Assert.notNull(config.getId(), "config cannt update");

        // 是否有任务在运行
        if (ScheduledTaskContainer.isStarted( Task.of(config))) {
            throw new TaskStateException();
        }

        Config rslt = configRep.save(config);

        // 加入到容器
        ScheduledTaskContainer.put(Task.of(rslt), ScheduledFutureTaskHolder.emptyHolder());
        return rslt;
    }
}
